package serial

import (
	"errors"
	"io"
	"sync"
	"time"
)

var ErrTimeout = errors.New("timeout")

type TimeoutRWC struct {
	io.ReadWriteCloser
	timeout   time.Duration
	peek      []byte
	ok        bool
	readBuf   []byte
	buf       LoopBuffer
	eventChan chan byte
	lock      sync.Mutex
	Err       error
}

func NewTimeoutRWC(conn io.ReadWriteCloser, readSize int, timeoutMs int64) *TimeoutRWC {
	m := new(TimeoutRWC)
	m.Setup(conn, readSize, timeoutMs)
	return m
}

func (m *TimeoutRWC) Setup(conn io.ReadWriteCloser, readSize int, timeoutMs int64) *TimeoutRWC {
	m.timeout = time.Millisecond * time.Duration(timeoutMs)
	readSize = min(max(readSize, 64), 65535)
	m.readBuf = make([]byte, readSize)
	m.buf.SetData(make([]byte, readSize+1024))
	m.buf.SetDisableEOF()
	m.eventChan = make(chan byte, 10)
	m.ReadWriteCloser = conn
	if conn != nil {
		m.ok = true
		go m.read()
	}
	return m
}

func (m *TimeoutRWC) SetRWC(conn io.ReadWriteCloser) {
	if conn == nil {
		panic("ReadWriteCloser is nil")
	}
	m.Close()
	m.ReadWriteCloser = conn
	m.ok = true
	m.clearEvent()
	go m.read()
}

// 判断连接是否关闭
func (m *TimeoutRWC) IsClose() bool {
	return !m.ok
}

// 重置
func (m *TimeoutRWC) Reset() {
	m.buf.Reset()
	m.peek = nil
	m.clearEvent()
}

// 清除事件
func (m *TimeoutRWC) clearEvent() {
	for len(m.eventChan) > 0 {
		<-m.eventChan
	}
}

func (m *TimeoutRWC) read() {
	for m.ok {
		m.lock.Lock()
		n := m.buf.AvailWrite()
		m.lock.Unlock()
		if n == 0 {
			m.eventChan <- 1
			continue
		}
		n = min(n, len(m.readBuf))
		num, err := m.ReadWriteCloser.Read(m.readBuf[:n])
		if err != nil {
			m.Err = err
			m.Close()
			break
		}
		if num == 0 {
			continue
		}
		if m.ok {
			m.lock.Lock()
			m.buf.Write(m.readBuf[:num])
			m.lock.Unlock()
			m.eventChan <- 1
		}
	}
}

// 带有超时机制的读取函数
func (m *TimeoutRWC) Read(data []byte) (num int, err error) {
	if !m.ok {
		return 0, io.EOF
	}
	if len(m.peek) > 0 {
		num = copy(data, m.peek)
		m.peek = m.peek[num:]
		return
	}

	if m.Err != nil {
		return 0, m.Err
	}

	defer m.clearEvent()

	m.lock.Lock()
	if m.buf.Len() > 0 {
		num, err = m.buf.Read(data)
		if err != nil {
			m.lock.Unlock()
			return 0, err
		}
		if num > 0 {
			m.lock.Unlock()
			return num, err
		}
	}
	m.lock.Unlock()

	select {
	case <-time.After(m.timeout):
		return 0, ErrTimeout
	case <-m.eventChan:
		m.lock.Lock()
		num, err = m.buf.Read(data)
		m.lock.Unlock()
	}
	return
}

func (m *TimeoutRWC) Write(data []byte) (num int, err error) {
	if m.Err != nil {
		return 0, m.Err
	}
	if !m.ok {
		return 0, io.EOF
	}
	num, err = m.ReadWriteCloser.Write(data)
	if err != nil {
		m.Err = err
		m.Close()
	}
	return
}
func (m *TimeoutRWC) ReafFull(data []byte) (num int, err error) {
	return io.ReadFull(m, data)
}

func (m *TimeoutRWC) Close() (err error) {
	if !m.ok {
		return io.EOF
	}
	err = m.ReadWriteCloser.Close()
	m.ok = false
	return
}

// 增加peek函数
func (m *TimeoutRWC) Peek(n int) (data []byte, err error) {
	if len(m.peek) > 0 {
		data = m.peek
		return
	}

	if !m.ok {
		return nil, io.EOF
	}

	data = make([]byte, n)
	num, err := m.Read(data)
	if err != nil {
		return nil, err
	}
	m.peek = data[:num]
	return m.peek, nil
}
